<template>
  <div>
    <a-layout>
      <a-layout-sider width="250px" :class="{ aside_main_show: !asideStatus }">
        <a-row>
          <a-col :span="22">
            模块目录
          </a-col>
          <!-- 更多选项按钮 -->
          <a-col :span="2">
            <a-dropdown>
              <a-icon type="ellipsis" />
              <a-menu slot='overlay'>
                <a-menu-item @click.native="showChange8">
                  新增目录
                </a-menu-item>
              </a-menu>
            </a-dropdown>
          </a-col>
        </a-row>
        <a-row>
          <a-input-search v-model="searchValue" style="margin-bottom: 8px" placeholder="请输入" @change="onSearch" allow-clear />
        </a-row>
        <a-row>
          <a-tree
            ref="tree"
            v-loading="loading1"
            :tree-data="contentsData"
            :expandedKeys="expandedKeys"
            :auto-expand-parent="autoExpandParent"
            @select="handleNodeClick"
            @expand="onExpand"
            :replace-fields="replaceFields"
          >
            <template slot="handle" slot-scope="item">
              <a-icon type="folder" />
              <span style="margin-left: 10px">{{ item.moduleCname }}</span>
              <!-- 更多选项按钮 -->
              <a-dropdown style="position:absolute; right: 10px;">
                <a-icon type="ellipsis" />
                <a-menu slot='overlay'>
                  <a-menu-item @click.native="showChange1(item.id)">
                    新增目录
                  </a-menu-item>
                  <a-menu-item @click.native="showChange2(item.id)">
                    编辑
                  </a-menu-item>
                  <a-menu-item @click.native="showChange3(item.id)">
                    删除
                  </a-menu-item>
                </a-menu>
              </a-dropdown>
            </template>
          </a-tree>
        </a-row>
      </a-layout-sider>
      <a-layout>
        <!-- aside侧边栏按钮 -->
        <div class="aside_open_close"  @click="asideChange">
          <i class="el-icon-arrow-left" v-if="asideOpen" />
          <i class="el-icon-arrow-right" v-else />
        </div>
        <a-layout-header style="position: relative; top: -60px;">
          <a-form :model="infoParams">
            <a-row>
              <!-- 接口查询框部分 -->
              <a-col :span="6">
                <a-form-item label="接口名称" :label-col="{ span: 8}" :wrapper-col="{ span: 16}">
                  <a-input v-model="infoParams.apiName" placeholder="请输入名称" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="接口中文名称" :label-col="{ span: 10}" :wrapper-col="{ span: 14}">
                  <a-input v-model="infoParams.apiCname" placeholder="请输入中文名称" />
                </a-form-item>
              </a-col>
              <a-col :span="5">
                <a-form-item label="接口状态" :label-col="{ span: 8}" :wrapper-col="{ span: 8}">
                  <a-select v-model="infoParams.apiStatus" allow-clear>
                    <a-select-option value="2">下线</a-select-option>
                    <a-select-option value="1">发布</a-select-option>
                  </a-select>
                </a-form-item>
              </a-col>
              <a-col :span="2">
                <a-button type="primary" @click="search">查询</a-button>
              </a-col>
              <a-col :span="3">
                <a-button @click="reset">重置</a-button>
              </a-col>
              <!-- 新增接口按钮 -->
              <a-col :span="2">
                <a-button type="primary" @click="showChange4">新增</a-button>
              </a-col>
            </a-row>
          </a-form>
        </a-layout-header>
        <!-- 接口数据表格 -->
        <a-layout-content style="position: relative; left: 18px; top: -60px;">
          <a-table
            v-loading="loading2"
            :columns="columns"
            :dataSource="tableData"
            :pagination="false"
            :scroll="{ y: 480 }"
            :default-sort="{prop: 'id', order: 'ascending'}"
            bordered
          >
            <span slot="apiStatus" slot-scope="text, record">
              <span v-if="record.apiStatus == 1" style="margin-right: 8px;">
                <i class="dotClass" style="background-color: #67C23A; float:left" />
                <span style="float: left;">发布</span>
              </span>
              <span v-if="record.apiStatus == 2" style="margin-right: 8px;">
                <i class="dotClass" style="background-color: #F56C6C; float:left" />
                <span style="float: left;">下线</span>
              </span>
            </span>
            <span slot="action" slot-scope="text, record">
              <a-row :gutter="16" style="color: rgb(0, 93, 223);">
                <a v-if="record.apiStatus == 1" @click="statusChange1(record)">
                  下线
                </a>
                <a v-if="record.apiStatus == 2" @click="statusChange2(record)">
                  发布
                </a>
                <a v-if="record.apiStatus == 1" @click="showChange5(record)">
                  测试
                </a>
                <a v-if="record.apiStatus == 2" @click="showChange6(record)">
                  编辑
                </a>
                <a @click="showChange7(record)">
                  删除
                </a>
              </a-row>
            </span>
          </a-table>
          <!--下面展示总共条数和切换页面-->
          <div class="paginationBox">
            <a-pagination
              v-show="total > 0"
              show-size-changer
              layout="total, prev, pager, next, sizes"
              :total="total"
              :page-size-options="[10, 20, 30, 40, 50]"
              v-model:current="pageForm.pageNum"
              :page-size="pageForm.pageSize"
              :show-total="total => `共${total}条`"
              @change="handleCurrentChange"
              @showSizeChange="handleSizeChange"
            >
              <template #buildOptionText="props">
                <span>{{ props.value }}条/页</span>
              </template>
            </a-pagination>
          </div>
        </a-layout-content>
      </a-layout>
    </a-layout>

    <!-- 目录新增和编辑 -->
    <a-modal :zIndex="1001" :title="moduleTitle" v-model:visible="show1" :footer="null">
      <a-form-model ref="moduleForm" :model="moduleForm" :rules="rule1">
        <a-row>
          <a-form-model-item label="目录名称" prop="moduleName">
            <a-input v-model="moduleForm.moduleName" placeholder="请输入名称" />
          </a-form-model-item>
        </a-row>
        <a-row>
          <a-form-model-item label="目录中文名称" prop="moduleCname">
            <a-input v-model="moduleForm.moduleCname" placeholder="请输入中文名称" />
          </a-form-model-item>
        </a-row>
        <a-row>
          <a-form-model-item label="描述" prop="remark">
            <a-input v-model="moduleForm.remark" placeholder="请输入描述" type="textarea" />
          </a-form-model-item>
        </a-row>
      </a-form-model>
      <div>
        <a-button @click="cancel1">取 消</a-button>
        <a-button type="primary" @click="submitModuleForm">保 存</a-button>
      </div>
    </a-modal>
    <!-- 目录删除 -->
    <a-modal :zIndex="1001" title="删除模块目录" v-model:visible="show2" :footer="null">
      <div>请问是否确定删除该项模块？</div>
      <div>
        <a-button type="primary" @click="delModuleData">确定</a-button>
        <a-button @click="cancel2">取消</a-button>
      </div>
    </a-modal>
    <!-- 接口新增和编辑 -->
    <a-modal :zIndex="1001" :title="infoTitle" v-model:visible="show3" :footer="null">
      <a-form-model ref="infoForm" :model="infoForm" :rules="rule2">
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="接口名称" prop="apiName">
              <a-input v-model="infoForm.apiName" placeholder="请输入名称" />
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="接口中文名称" prop="apiCname">
              <a-input v-model="infoForm.apiCname" placeholder="请输入中文名称" />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row>
          <a-form-model-item label="请求接口地址" prop="requestUrl">
            <a-input v-model="infoForm.requestUrl" placeholder="请输入地址" type="textarea" />
          </a-form-model-item>
        </a-row>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="接口协议" prop="requestMethod">
              <a-select v-model="infoForm.requestMethod">
                <a-select-option value="GET">GET</a-select-option>
                <a-select-option value="POST">POST</a-select-option>
                <a-select-option value="PUT">PUT</a-select-option>
                <a-select-option value="DELETE">DELETE</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="是否发布">
              <a-switch v-model:checked="switchs" active-color="#13ce66" />
            </a-form-model-item>
          </a-col>
        </a-row>
      </a-form-model>
      <div>
        <a-button @click="cancel3">取 消</a-button>
        <a-button type="primary" @click="submitInfoForm">保 存</a-button>
      </div>
    </a-modal>
    <!-- 接口测试 -->
    <a-modal :zIndex="1001" title="接口测试" v-model:visible="show4" :footer="null">
      <a-row :gutter="16">
        <a-col :span="12">
          <a-row>
            <a-col :span="16">
              输入参数
            </a-col>
            <a-col :span="8">
              <a-button type="primary" @click="apiTest">测试</a-button>
            </a-col>
          </a-row>
          <a-row>
            <a-input v-model="testParam" placeholder="请输入可测试参数" type="textarea" resize="none" :autosize="{ minRows: 10}" />
          </a-row>
        </a-col>
        <a-col :span="12">
          <a-row>
            响应结果
          </a-row>
          <a-row>
            <a-input v-model="testResponse" placeholder="此处输出响应结果" type="textarea" resize="none" :autosize="{ minRows: 11}" />
          </a-row>
        </a-col>
      </a-row>
      <div>
        <a-button @click="cancel4">关 闭</a-button>
      </div>
    </a-modal>
    <!-- 接口删除 -->
    <a-modal :zIndex="1001" title="删除接口" v-model:visible="show5" :footer="null">
      <div>请问是否确定删除该接口？</div>
      <div>
        <a-button type="primary" @click="delInfoData">确定</a-button>
        <a-button @click="cancel5">取消</a-button>
      </div>
    </a-modal>
  </div>
</template>
<script>
import { listModule, getModule, addModule, editModule, delModule, listInfo, addInfo, editInfo, delInfo, testApi, noApi, offApi } from '@/api/system/outapi/manage'

const dataList = []
const generateList = (data) => {
    for (let i = 0; i < data.length; i++) {
        const node = data[i]
        const id = node.id
        const moduleCname=node.moduleCname
        dataList.push({ id, moduleCname: moduleCname })
        if (node.children) {
            generateList(node.children)
        }
    }
}
const getParentKey = (key, tree) => {
  let parentKey
  for (let i = 0; i < tree.length; i++) {
    const node = tree[i]
    if (node.children) {
      if (node.children.some((item) => item.id === key)) {
        parentKey = node.id
      } else if (getParentKey(key, node.children)) {
        parentKey = getParentKey(key, node.children)
      }
    }
  }
  return parentKey
}
const setStyleDisplay = (key, nodes) => {
  let nums = 0
  for (let data of nodes) {
    let bl = false
    if (data.moduleCname.indexOf(key) > -1) {
      bl = true
      nums += 1
    }
    if (!!data.children) {
      if (data.children.length > 0) {
        let count = setStyleDisplay(key, data.children)
        // 如果想 子节点有key 即使父节点没有key也显示的话 添加下面的语句 
        nums += count
        if (!bl && count == 0) {
          bl = false
        } else {
          bl = true
        }
      }
    }
    if (bl) {
      delete data['style']
    } else {
      data['style'] = 'display: none'
    }
  }
  return nums
}

export default {
  name: 'Service',
  data() {
    return {
      loading1: false, // 目录遮罩层
      loading2: false, // 表格遮罩层
      showPop1: false, // 弹框开关
      showPop2: false, // 弹框开关
      show1: false, // 目录新增编辑表单弹窗开关
      show2: false, // 目录删除弹窗开关
      show3: false, // 接口新增编辑表单弹窗开关
      show4: false, // 接口测试弹窗开关
      show5: false, // 接口删除弹窗开关
      asideStatus: true, // 侧边栏开关
      asideOpen: true, // 侧边栏按钮
      vueId: null,
      switchs: false, // 选择开关
      searchValue: '', // 搜索框输入内容
      total: 0, // 表格数据总条数
      moduleTitle: null, // 目录新增编辑表单弹窗标题
      infoTitle: null, // 接口新增编辑表单弹窗标题
      filterText: null, // 目录搜索关键字
      testParam: null, // 测试参数
      testResponse: null, // 测试响应
      contentsData: [], // 目录数据
      tableData: [], // 表格数据
      expandedKeys: [], // 目录展开节点数组
      autoExpandParent: true,
      columns: [{ // 表格内容
        title: '',
        customRender: (text, record, index) => `${index + 1}`,
        align: 'center'
      },{
        title: '接口名称',
        dataIndex: 'apiName',
        key: 'apiName',
        align: 'left'
      },{
        title: '接口中文名称',
        dataIndex: 'apiCname',
        key: 'apiCname',
        align: 'left'
      },{
        title: '请求接口地址',
        dataIndex: 'requestUrl',
        key: 'requestUrl',
        align: 'left'
      },{
        title: '请求协议',
        dataIndex: 'requestMethod',
        key: 'requestMethod',
        align: 'left'
      },{
        title: '状态',
        dataIndex: 'apiStatus',
        key: 'apiStatus',
        align: 'left',
        scopedSlots: { customRender: 'apiStatus' }
      },{
        title: '操作',
        align: 'center',
        scopedSlots: { customRender: 'action' }
      }],
      pageForm: { // 页面对象
        pageNum: 1,
        pageSize: 10
      },
      replaceFields: { // 节点结构
        title: 'moduleCname',
        key: 'id',
        scopedSlots: 'scopedSlots',
        children: 'children'
      },
      moduleForm: { // 目录表单对象
        id: null,
        moduleName: null,
        moduleCname: null,
        parentId: null,
        remark: null,
        createTime: null, // 不传值
        createBy: null, // 不传值
        updateBy: null, // 不传值
        updateTime: null // 不传值
      },
      infoParams: { // 接口查询表单对象
        pageNum: null,
        pageSize: null,
        id: null,
        apiName: null,
        apiCname: null,
        requestUrl: null,
        moduleId: null,
        apiStatus: null,
        requestMethod: null,
        requestParam: null
      },
      infoForm: { // 接口表单对象
        id: null,
        apiName: null,
        apiCname: null,
        requestUrl: null,
        moduleId: null,
        remark: null, // 不传值
        apiStatus: null,
        createTime: null, // 不传值
        createBy: null, // 不传值
        updateBy: null, // 不传值
        updateTime: null, // 不传值
        requestMethod: null, // 不传值
        requestParam: null // 不传值
      },
      rule1: { // 目录新增编辑表单规则
        moduleName: [
          { required: true, message: '目录名称不能为空', trigger: 'blur' }
        ],
        moduleCname: [
          { required: true, message: '目录中文名称不能为空', trigger: 'blur' }
        ],
        remark: [
        { required: true, message: '描述不能为空', trigger: 'blur' }
        ]
      },
      rule2: { // 接口新增编辑表单规则
        apiName: [
          { required: true, message: '接口名称不能为空', trigger: 'blur' }
        ],
        apiCname: [
          { required: true, message: '接口中文名称不能为空', trigger: 'blur' }
        ],
        requestMethod: [
          { required: true, message: '请求接口协议不能为空', trigger: 'blur' }
        ],
        requestUrl: [
          { required: true, message: '请求接口地址不能为空', trigger: 'blur' }
        ]
      }
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  created() {
    this.initVue()
  },
  methods: {
    initVue() { // 页面初始化
      this.initModule()
      this.initInfo()
      this.infoParams.pageNum = this.pageForm.pageNum
      this.infoParams.pageSize = this.pageForm.pageSize
      this.getModuleData()
      this.getInfoData()
    },
    initModule() { // 重置目录表单对象
      this.moduleForm = {
        id: null,
        moduleName: null,
        moduleCname: null,
        parentId: null,
        remark: null,
        createTime: null,
        createBy: null,
        updateBy: null,
        updateTime: null
      }
    },
    initParams() {
      this.infoParams = { // 重置参数表单
        pageNum: null,
        pageSize: null,
        id: null,
        apiName: null,
        apiCname: null,
        requestUrl: null,
        moduleId: null,
        apiStatus: null,
        requestMethod: null,
        requestParam: null
      }
    },
    initInfo() { // 重置接口表单对象
      this.infoForm = {
        id: null,
        apiName: null,
        apiCname: null,
        requestUrl: null,
        moduleId: null,
        remark: null,
        apiStatus: null,
        createTime: null,
        createBy: null,
        updateBy: null,
        updateTime: null,
        requestMethod: null,
        requestParam: null
      }
    },
    reset() { // 重置查询框
      this.infoParams.apiName = null
      this.infoParams.apiCname = null
      this.infoParams.apiStatus = null
    },
    search() { // 查询
      this.pageForm.pageNum = 1
      this.infoParams.pageNum = this.pageForm.pageNum
      this.infoParams.pageSize = this.pageForm.pageSize
      this.getInfoData()
    },
    asideChange() {
      this.asideStatus = !this.asideStatus 
      if (this.asideStatus) {
        this.asideOpen = true
      } else {
        this.asideOpen = false
      }
    },
    showChange1(id) { // 目录新增弹窗打开
      this.initModule()
      this.moduleForm.parentId = id
      this.moduleTitle = '新增目录'
      this.show1 = true
    },
    showChange2(id) { // 目录编辑弹窗打开
      this.moduleForm.id = id
      getModule(this.moduleForm.id).then(response => {
        this.moduleForm = response.data
        this.moduleTitle = '编辑目录'
        this.show1 = true
      })
    },
    showChange3(id) { // 目录删除弹窗打开
      this.moduleForm.id = id
      this.show2 = true
    },
    showChange4() { // 接口新增弹窗打开
      if (this.vueId == null) {
        this.$alert('请先选择模块', '无法新增', {
          confirmButtonText: '确定'
        })
      } else {
        this.initInfo()
        this.switchs = false
        this.infoTitle = '新增接口'
        this.show3 = true
      }
    },
    showChange5(data) { // 接口测试弹窗打开
      this.infoForm = data
      this.show4 = true
    },
    showChange6(data) { // 接口编辑弹窗打开
      this.infoForm = data
      if (this.infoForm.apiStatus == '1') {
        this.switchs = true
      } else {
        this.switchs =false
      }
      this.infoTitle = '编辑接口'
      this.show3 = true
    },
    showChange7(data) { // 接口删除弹窗打开
      this.infoForm.id = data.id
      this.show5 = true
    },
    showChange8() { // 目录根节点新增弹窗打开
      this.initModule()
      this.moduleForm.parentId = 0
      this.moduleTitle = '新增目录'
      this.show1 = true
    },
    cancel1() { // 目录新增编辑取消
      this.show1 = false
    },
    cancel2() { // 目录删除取消
      this.show2 = false
    },
    cancel3() { // 接口新增编辑取消
      this.show3 = false
    },
    cancel4() { // 接口测试关闭
      this.show4 = false
    },
    cancel5() { // 接口删除取消
      this.show5 = false
    },
    submitModuleForm() { // 提交新增编辑目录表单数据
      this.$refs["moduleForm"].validate(valid => {
        if (valid) {
          if (this.moduleForm.id == null) { // 新增
            addModule(this.moduleForm).then(response => {
              this.show1 = false
              this.initModule()
              this.getModuleData()
            })
          } else { // 编辑
            editModule(this.moduleForm).then(response => {
              this.show1 = false
              this.initModule()
              this.getModuleData()
            })
          }
        }
      })
    },
    submitInfoForm() { // 提交新增编辑接口表单数据
      this.$refs["infoForm"].validate(valid => {
        if (valid) {
          if (this.switchs === true) {
            this.infoForm.apiStatus = '1'
          } else {
            this.infoForm.apiStatus = '2'
          }
          if (this.infoForm.id == null) { // 新增
            this.infoForm.moduleId = this.vueId
            addInfo(this.infoForm).then(response => {
              this.show3 = false
              this.initParams()
              this.pageForm.pageNum = 1
              this.infoParams.moduleId = this.vueId
              this.infoParams.pageNum = this.pageForm.pageNum
              this.infoParams.pageSize = this.pageForm.pageSize
              this.getInfoData()
            })
          } else { // 编辑
            editInfo(this.infoForm).then(response => {
              this.show3 = false
              this.getInfoData()
            })
          }
        }
      })
    },
    statusChange1(data) { // 下线接口
      this.infoForm.id = data.id
      offApi(this.infoForm).then(response => {
        this.initInfo()
        this.getInfoData()
      })
    },
    statusChange2(data) { // 发布接口
      this.infoForm.id = data.id
      noApi(this.infoForm).then(response => {
        this.initInfo()
        this.getInfoData()
      })
    },
    getModuleData() { // 获取目录数据
      this.loading1 = true
      listModule().then(response => {
        this.contentsData = this.addData(response.rows)
        generateList(this.contentsData)
        this.expandedKeys = []
        this.loading1 = false
      })
    },
    delModuleData() { // 删除目录数据
      delModule(this.moduleForm.id).then(response => {
        this.show2 = false
        this.initModule()
        this.getModuleData()
      })
    },
    getInfoData() { // 获取表格数据
      this.loading2 = true
      listInfo(this.infoParams).then(response => {
        this.total = response.total
        this.tableData = response.rows
        this.loading2 = false
      })
    },
    delInfoData() { // 删除接口数据
      delInfo(this.infoForm.id).then(response => {
        this.show5 = false
        this.initInfo()
        this.getInfoData()
      })
    },
    filterNode(value, data) {
      if (!value) return true
      return data.moduleCname.indexOf(value) !== -1
    },
    getStatusTru(status) { // 状态表达转化
      if (status == 1) {
        return '发布'
      } else {
        return '下线'
      }
    },
    handleNodeClick(key, e) { // 点击目录节点
      this.vueId = key[0]
      this.infoParams.moduleId = key[0]
      this.getInfoData()
    },
    apiTest() { // 接口测试
      testApi(this.infoForm.id).then(response => {
        
      })
    },
    handleCurrentChange() { // 切换页面
      this.infoParams.moduleId = this.vueId
      this.infoParams.pageNum = this.pageForm.pageNum
      this.infoParams.pageSize = this.pageForm.pageSize
      this.getInfoData()
    },
    handleSizeChange(cur, val) { // 切换页面大小
      this.infoParams.moduleId = this.vueId
      this.pageForm.pageNum = 1
      this.pageForm.pageSize = val
      this.infoParams.pageNum = this.pageForm.pageNum
      this.infoParams.pageSize = this.pageForm.pageSize
      this.getInfoData()
    },
    addData(data) { // 添加必要数据
      for(let item in data) {
        this.$set(data[item], 'scopedSlots', { title: 'handle' })
        if (data[item].hasOwnProperty('children')) {
          this.addData(data[item].children)
        }
      }
      return data
    },
    onExpand(expandedKeys) {
      this.expandedKeys = expandedKeys
      this.autoExpandParent = false
    },
    onSearch(e){
      if(this.searchValue === '') {
        this.getModuleData()
        return
      }
      const value = e.target.value
      const expandedKeys = dataList
      .map((item) => {
        if (item.moduleCname.indexOf(value) > -1) {
          return getParentKey(item.id, this.contentsData)
        }
        return null
      })
      .filter((item, i, self) => item && self.indexOf(item) === i)
      setStyleDisplay(value, this.contentsData)
      Object.assign(this, {
        expandedKeys,
        autoExpandParent: true,
      })
    }
  }
}
</script>
<style>
.ant-layout-sider {
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
}
.ant-layout-header {
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
}
.aside_main_show{
  display: none;
}
.aside_open_close{
  position: relative;
  left: 0;
  top: 40%;
  width: 18px;
  height: 60px;
  line-height: 60px;
  color: rgb(131,159,163);
  background-color: rgb(255, 255, 255);
  border-radius: 0 6px 6px 0;
  border: 1px rgb(198, 196, 196) solid;
  font-size: 20px;
  z-index: 1000;
  cursor: pointer;
}
.dotClass {
  width: 8px;
  height: 8px;
  margin-top: 7px;
  margin-right: 3px;
  border-radius: 50%;
  display: block;
}
</style>
